﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Documents;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.UI.CustomComponents;
using PSE.Deployment.Util;

namespace PSE.Deployment.SetupBase.UI.CustomComponents
{
    public partial class GroupsTreeView : UserControl
    {
        private IEnumerable<Group> _groups;
        private List<TreeViewModel> _treeViewModels;
        private List<TreeViewModel> _allTreeViewModels;

        public IEnumerable<Group> Groups
        {
            get { return _groups; }
            set { _groups = value; }
        }

        public List<TreeViewModel> TreeViewModels
        {
            get { return _treeViewModels; }
            set { _treeViewModels = value; }
        }

        public List<TreeViewModel> AllTreeViewModels
        {
            get { return _allTreeViewModels; }
            set { _allTreeViewModels = value; }
        }

        public event CheckedChangingEventHandler CheckStateChanging;
        public delegate void CheckedChangingEventHandler(object sender, CheckedChangingEventArgs e);

        public event CheckedChangedEventHandler CheckStateChanged;
        public delegate void CheckedChangedEventHandler(object sender, CheckedChangedEventArgs e);

        public GroupsTreeView()
        {
            this.InitializeComponent();

            Groups = SetupMainFactory.GetInstance().Configuration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).SelectDeep(g => g.Dependencies);

            TreeViewModels = GroupToModel(SetupMainFactory.GetInstance().Configuration.SystemInfo.Groups);

            AllTreeViewModels = TreeViewModels.SelectDeep(t => t.Children).ToList();

            treeView.ItemsSource = TreeViewModels;
        }

        private List<TreeViewModel> GroupToModel(List<Group> groups)
        {
            List<TreeViewModel> items = new List<TreeViewModel>();

            foreach (Group group in groups)
            {
                TreeViewModel treeViewItem = new TreeViewModel(group.Id, group.Name);

                if (group.SubGroups != null && group.SubGroups.Count > 0)
                    treeViewItem.Children = GroupToModel(group.SubGroups);

                treeViewItem.IsChecked = group.Install;
                treeViewItem.CheckStateChanging += new TreeViewModel.CheckedChangingEventHandler(treeViewItem_CheckStateChanging);
                treeViewItem.CheckStateChanged += new TreeViewModel.CheckedChangedEventHandler(treeViewItem_CheckStateChanged);
                treeViewItem.Initialize();

                items.Add(treeViewItem);
            }

            return items;
        }

        /// <summary>
        /// Tratar o evento que indica que o estado da propriedade IsChecked foi alterado
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void treeViewItem_CheckStateChanged(object sender, CheckedChangedEventArgs e)
        {
            if (CheckStateChanged != null)
                CheckStateChanged(sender, e);
        }

        void treeViewItem_CheckStateChanging(object sender, CheckedChangingEventArgs e)
        {
            CheckedChangingEventArgs args = new CheckedChangingEventArgs(e.IsChecked);
            if (CheckStateChanging != null)
                CheckStateChanging(sender, args);

            TreeViewModel model = (TreeViewModel)sender;
            Group affectedGroup = Groups.Single(g => g.Id == model.Id);
            bool? install = affectedGroup.Install;

            if (!args.Cancel)
            {
                affectedGroup.Install = e.IsChecked;
                ChangeDependencies(affectedGroup.Dependencies, e.IsChecked);
            }
            else //if (args.Cancel)
            {
                e.Cancel = true;
                affectedGroup.Install = install;
                ChangeDependencies(affectedGroup.Dependencies, install);
            }
        }

        private void ChangeDependencies(List<Group> dependencies, bool? value)
        {
            if (dependencies != null)
            {
                foreach (Group item in dependencies)
                {
                    if (value.GetValueOrDefault())
                    {
                        Groups.Where(g => g.Id == item.Id).ToList().ForEach(g => g.Install = true);
                    }
                    else
                    {
                        IEnumerable<Group> parentGroups = from g in Groups
                                                          where g.Id == item.Id
                                                          select g.ParentGroup;

                        IEnumerable<Group> originalParentGroups = from g in Groups
                                                                  from p in parentGroups
                                                                  where p != null && 
                                                                        g.Id == p.Id 
                                                                  select g;

                        if (originalParentGroups.All(g => g.Install == false))
                            Groups.Where(g => g.Id == item.Id).ToList().ForEach(g => g.Install = false);
                    }

                    ChangeDependencies(item.Dependencies, value);
                }
            }
        }
    }
}
